package cn.whale.pay.service.impl;

import cn.whale.basic.constants.MQConstants;
import cn.whale.pay.domain.PayFlow;
import cn.whale.pay.dto.AlipayNotifyDto;
import cn.whale.pay.dto.PayDto;
import cn.whale.pay.properties.AlipayProperties;
import cn.whale.pay.service.IAliPayService;
import cn.whale.pay.service.IPayFlowService;
import cn.whale.task.api.PayResultToMQApi;
import cn.whale.task.domain.MqLog;
import com.alibaba.fastjson.JSON;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.util.ResponseChecker;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
import java.util.Random;

@Service
@Slf4j
@Transactional
public class AliPayServiceImpl implements IAliPayService {

    @Autowired
    private AlipayProperties alipayProperties;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private IPayFlowService payFlowService;
    @Autowired
    private PayResultToMQApi payResultToMQApi;

    @Override
    public String payApply(PayDto payDto) {
        // 1. 设置参数（全局只需设置一次）
        Factory.setOptions(alipayProperties.getOptions());
        log.info("notifyUrl:"+alipayProperties.getNotifyUrl());;
        try {
            // 2. 发起API调用,网页支付
            //String subject, String outTradeNo, String totalAmount, String returnUrl
            AlipayTradePagePayResponse response = Factory.Payment.Page().pay(
                    payDto.getTitle(), payDto.getTradeNo(), payDto.getAmount().toString(), alipayProperties.getReturnUrl());
            // 3. 处理响应或异常
            if (ResponseChecker.success(response)) {
                log.info("支付申请成功");
                payFlowService.insert(createPayFlow(payDto.getTitle(),payDto.getAmount(),payDto.getTradeNo()));
                return response.getBody();
            } else {
                log.error("支付申请失败");
            }

        } catch (Exception e) {
            System.err.println("调用遭遇异常，原因：" + e.getMessage());
            log.info("支付申请异常[{}]",e.getMessage());
            throw new RuntimeException(e.getMessage(), e);
        }
        return "支付失败";
    }

    @Override
    public String alipayNotify(AlipayNotifyDto alipayNotifyDto) {

        //签名
        if (!notifySign(alipayNotifyDto)) return "ERROR";
        return "SUCCESS";
    }

    private boolean notifySign(AlipayNotifyDto alipayNotifyDto) {
        if(!StringUtils.hasLength(alipayNotifyDto.getSign())){
            log.info("签名错误....");
            return false;
        }
        try {
            boolean signSuccess = Factory.Payment.Common().verifyNotify(JSON.parseObject(JSON.toJSONString(alipayNotifyDto), Map.class));
            if(!signSuccess){
                log.info("签名错误....");
                return false;
            }
            //修改流水状态
            PayFlow payFlow = payFlowService.selectByPayNo(alipayNotifyDto.getOut_trade_no());
            if(payFlow == null){ return false;}

            //幂等判断 ,支付记录已经被修改了就不要在修改了
            if(payFlow.getPayStatus() != PayFlow.STATUS_APPLY){ return false;}

            if(signSuccess && alipayNotifyDto.isTradeSuccess()) {
                payFlow.setPayStatus(PayFlow.STATUS_PAY_SUCCESS);
                payFlow.setResultDesc("支付成功");
                payFlowService.updateById(payFlow);

                //把消息放到MQ中订单服务进行消费
                //唯一标示
                CorrelationData correlationData = new CorrelationData(alipayNotifyDto.getOut_trade_no());

                //交换机队列
                String exchnageOrderKill = MQConstants.EXCHNAGE_ORDER_KILL;
                String routingkeyQueuePayNotify = MQConstants.ROUTINGKEY_QUEUE_PAY_NOTIFY;

                //保存记录到DB
                insertMqLog(JSON.toJSONString(alipayNotifyDto),correlationData.getId(),exchnageOrderKill,routingkeyQueuePayNotify);

                //测试代码，模拟消息投递失败
                rabbitTemplate.convertAndSend(exchnageOrderKill,routingkeyQueuePayNotify,alipayNotifyDto,correlationData);
                log.info("支付结果投递到MQ....EXCHANGE = {} , QUEUE = {}",exchnageOrderKill,routingkeyQueuePayNotify);

                return true;
            }else{
                payFlow.setPayStatus(PayFlow.STATUS_PAY_ERROR);
                payFlow.setResultDesc("支付失败["+alipayNotifyDto.getMsg()+"]");
                payFlowService.updateById(payFlow);
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("签名错误....");
        }
        return false;
    }

    private PayFlow createPayFlow(String intro, BigDecimal amount,String orderNo){
        return new PayFlow(intro,amount,PayFlow.TYPE_BUY_COURSE_ORDER,
                PayFlow.STATUS_APPLY,"支付中",null,orderNo);
    }

    private void insertMqLog(String content,String correlationDataId,String exchange,String routingky){
        //发送失败
        MqLog MqLog = new MqLog();
        MqLog.setStatus(MqLog.STATUS_SUCCESS);
        MqLog.setExchange(exchange);
        MqLog.setRoutingkey(routingky);
        MqLog.setCreateTime(new Date());
        MqLog.setContent(content);
        MqLog.setMessageId(correlationDataId);
        payResultToMQApi.save(MqLog);
    }


}
